home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 4653 < prev    next >
Encoding:
Text File  |  1996-08-06  |  6.1 KB  |  205 lines

  1. Path: telepost.no!usenet
  2. From: Carsten Arnholm <ca@sesam.dnv.no>
  3. Newsgroups: comp.lang.fortran,comp.lang.c++
  4. Subject: Re: How to link Fortran with c++  ??
  5. Date: 31 Jan 1996 14:42:57 GMT
  6. Organization: DNV
  7. Message-ID: <4env5h$3ai@nms.telepost.no>
  8. References: <310DD74F.59E2@imacsg1.epfl.ch>
  9. NNTP-Posting-Host: hugin.sesam.dnv.no
  10. Mime-Version: 1.0
  11. Content-Type: text/plain; charset=us-ascii
  12. Content-Transfer-Encoding: 7bit
  13. X-Mailer: Mozilla 1.1 (Windows; I; 32bit)
  14.  
  15. Niels Hilbrink <Niels@imacsg1.epfl.ch> wrote:
  16. >Hi,
  17. >
  18. >I have to link a piece of fortran code with c++ code but since if never
  19. >done that before I'd like to know a) can it be done and b) is it
  20. >difficult.
  21. >
  22. >Everything concerning this subject is welcome.
  23. >
  24. >Gr.
  25. >Niels Hiblrink
  26. >
  27. >
  28. >-- 
  29. >
  30. >   The most overlooked advantage to owning a computer is 
  31. >   that if they foul up there's no law against wacking   
  32. >   them around a little.                                 
  33. >
  34. >------------------------------------------------------------
  35. >Koen D'Hondt                          Niels Hilbrink
  36. >koen@@dutlhs1.lr.tudelft.nl      niels@dutlcc3.lr.tudelft.nl
  37. >
  38. >**** Ripley Software Development ****
  39. >(finger niels@dutlcc3.lr.tudelft.nl for more information.)
  40. >------------------------------------------------------------
  41.  
  42. Hi there,
  43.  
  44.  
  45. Mixed language programming (C++/FORTRAN 77) is not as hard as 
  46. it may seem.
  47.  
  48. The only non-trivial problem you must solve is fortran CHARACTERs. 
  49. You need to write a minimal CHARACTER class in C++. 
  50.  
  51. If you require single-source portability, it becomes slightly
  52. more complicated, but not impossible.
  53.  
  54. Below follows a summary of some stuff that I have done, plus
  55. some additional thoughts. 
  56.  
  57.  
  58.  
  59. typedef int     INTEGER;
  60. typedef float   REAL;
  61. typedef int     LOGICAL; 
  62.  
  63. #include "character.h"  // CHARACTER class (see below)
  64.  
  65. #define  SUBROUTINE        extern "C" void __stdcall
  66. #define  INTEGER_FUNCTION  extern "C" INTEGER __stdcall
  67. #define  REAL_FUNCTION     extern "C" REAL __stdcall
  68.  
  69.  
  70.  
  71. The CHARACTER class may look something like this:
  72.  
  73.  
  74.  
  75. #include <string.h>
  76.  
  77. /*
  78.   class CHARACTER
  79.   ===============
  80.   A minimal class used when passing C-string arguments from C++ to
  81.   FORTRAN 77 (received as FORTRAN 77 CHARACTER strings), and subsequently
  82.   returned back to C++ as properly zero terminated c-strings.
  83.  
  84.   Method used for zero-termination:
  85.   =================================
  86.   When the CHARACTER destructor is activated (typically when the
  87.   CHARACTER object goes out of scope within a C++ stub function)
  88.   the zero-termination of the c-string is automatically managed.
  89.  
  90.   FORTRAN Assumptions:
  91.   ====================
  92.   (1) FORTRAN truncates assigned strings when CHARACTER variable is too short
  93.   (2) FORTRAN pads CHARACTER variable with blanks when assigned string is short
  94.   (3) FORTRAN represents a CHARACTER as a string pointer followed by a length
  95.  
  96.   Author: Carsten A. Arnholm, 20-AUG-1995
  97. */
  98.  
  99. class CHARACTER {
  100. public:
  101.     CHARACTER(char* cstring) : rep(cstring), len(strlen(cstring)) {};
  102.     CHARACTER(char* cstring, const size_t lstr);
  103.    ~CHARACTER();
  104. public:
  105.     char*   rep;  // Actual string
  106.     size_t  len;  // String length, used by FORTRAN intrinsic function LEN()
  107. };
  108.  
  109. inline CHARACTER::CHARACTER(char* cstring, const size_t lstr) : rep(cstring), len(lstr-1)
  110. {
  111.    size_t actual = strlen(rep);
  112.    for(size_t i=actual;i<len;i++) rep[i]=' ';
  113.    rep[len]='\0';
  114. }
  115.  
  116. inline CHARACTER::~CHARACTER() {
  117.    for(size_t i=strlen(rep)-1;i>=0;i--) {
  118.      if(rep[i] != ' ') {
  119.         rep[i+1] = '\0';
  120.         break;
  121.      }
  122.    }
  123. }
  124.  
  125.  
  126. now you can declare FORTRAN subroutine prototypes in C++:
  127.  
  128. SUBROUTINE MYSUB(INTEGER& I1, CHARACTER C1, INTEGER& I2);
  129.  
  130. To create a portable solution, do the following:
  131.  
  132. a) Write header files for your FORTRAN libraries as shown above.
  133. b) Compile FORTRAN code and create *.lib files.
  134. c) Include the FORTRAN library header files in your C++ code.
  135. d) Call FORTRAN according to above prototype example.
  136. e) Compile C++ code and link with FORTRAN libraries
  137. f) This executes directly for Visual C++ 2.1 & 4.0 in combination
  138.    With Fortran Powerstation
  139.  
  140. porting to other machines:
  141.  
  142. a) Leave C++ and Fortran code untouched (single source requirement!)
  143. b) Write a small C++ program that read your FORTRAN library header files, 
  144.    and generate:
  145.    b.1: a platform-specific header file for the fortran
  146.         library. Here you deal with upper/lowercase names,
  147.         trailing underscores, character lengths etc.
  148.    b.2: a platform-specific *.CPP file containing inline
  149.         functions that convert from 
  150.         MYSUB(INTEGER& I1, CHARACTER C1, INTEGER& I2)
  151.         to
  152.         mysub_(int& I1, char* C1.rep, int& I2, int C1.len)
  153.  
  154.         (example above is for for SGI)
  155. c) Compile & link this generated code with your application.
  156. e) Should execute on basically any platform (UNIX, VMS, ...)
  157.  
  158.  
  159. Other issues
  160. ============
  161.  
  162. a) Calling/linkage convention (C++).
  163.    This is taken care of through the use of the statement: extern "C"
  164.    This avoids name mangling which is not used in FORTRAN.
  165.  
  166. b) Routine names
  167.    An ANSI standard FORTRAN routine name should be defined in UPPERCASE
  168.    and max 6 characters. This does not, however, mean that the name
  169.    used when calling from C/C++ should be in uppercase. On the SGI machine
  170.    (i.e. unix) the routine must be in lowercase with a trailing underscore.
  171.    On other unix boxes, you may need a leading underscore and/or uppercase
  172.    name.
  173.  
  174.    Example:
  175.    FORTRAN                              :          SUBROUTINE MYSUB
  176.    Machine-dependent C++ prototype (SGI):     extern "C" void mysub_();
  177.  
  178. c) Parameter types and argument passing
  179.    FORTRAN will always require parameters to be passed by reference
  180.                
  181.    FORTRAN                              :  SUBROUTINE MYSUB(IVAL)
  182.                                            INTEGER          IVAL
  183.  
  184.    Machine-dependent C++ prototype (SGI):  extern "C" void mysub_(int& IVAL);
  185.  
  186.  
  187. d) Machine dependent comparison of language types:
  188.  
  189.    FORTRAN               C++ 
  190.    =======               ===
  191.    INTEGER               int&
  192.    REAL                  float&
  193.    LOGICAL               int&
  194.    CHARACTER             char*   (+ size_t length )
  195.    DOUBLE PRECISION      double&
  196.  
  197. good luck,
  198.  
  199. Carsten Arnholm
  200. ca@sesam.dnv.no 
  201.  
  202.  
  203.  
  204.  
  205.